/**
 * 
 */
package com.alibam.core.wechat.oauth;

import java.io.Serializable;

import org.apache.log4j.Logger;

import com.alibam.core.wechat.util.HttpUtils;
import com.alibaba.fastjson.JSONObject;
import com.alibam.core.wechat.common.Config;
import com.alibam.core.wechat.exception.WeChatException;
import com.alibam.core.wechat.util.WeChatUtil;

/**
 * OAuth认证拉去用户信息
 * 
 * @author Alibam 开发指导文档：
 *         http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
 */
public class OAuth2Holder implements Serializable {

	private static final long serialVersionUID = 6514603504927047590L;

//	Logger logger = Logger.getLogger(OAuth2Holder.class);

	public static final String OAUTH_SCOPE_SNSAPI_BASE = "snsapi_base";
	public static final String OAUTH_SCOPE_SNSAPI_USERINFO = "snsapi_userinfo";

	private OAuthAccessToken oAuthAccessToken;
	private OAuthUserInfo oAuthUserInfo;
//	// accessToken 创建时间
//	private Date refreshDate;
	
	
	/**
	 * 微信用户第一次使用
	 * 
	 * @param code
	 * @throws WeChatException 
	 */
	public OAuth2Holder(String code) throws WeChatException {
		this.oAuthAccessToken = callForOAuthAccessToken(code);
		this.oAuthUserInfo = callForOAuthUserinfo(oAuthAccessToken);
	}
	
	/**
	 * 微信用户刷新信息使用
	 * 
	 * @param _oAuthAccessToken
	 */
	public OAuth2Holder(OAuthAccessToken _oAuthAccessToken) {
		this.oAuthAccessToken = callForOAuthAccessTokenByRefreshToken(_oAuthAccessToken.getRefresh_token());
		this.oAuthUserInfo = callForOAuthUserinfo(oAuthAccessToken);
	}
	
	/**
	 * 获取OAuth2认证地址。
	 * 
	 * @param redirectURI
	 *            重定向地址
	 * @param scope
	 *            OAuth scope ： snsapi_base 、snsapi_userinfo
	 * @return
	 */
	public static String getOAuthUrl(String redirectURI, String scope) {
		scope = scope == null ? OAUTH_SCOPE_SNSAPI_USERINFO : scope;
		String appid = Config.instance().getAppid();
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
				+ appid
				+ "&redirect_uri="
				+ redirectURI
				+ "&response_type=code&scope="
				+ scope
				+ "&state=STATE#wechat_redirect";
		return url;
	}

	/**
	 * 根据code获取OAuthAccessToken
	 * 
	 * 对应文档认证步骤2
	 * @param code
	 * @return
	 * @throws WeChatException 
	 */
	private OAuthAccessToken callForOAuthAccessToken(String code) throws WeChatException {
		String appid = Config.instance().getAppid();
		String secret = Config.instance().getAppSecret();
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
				+ appid + "&secret=" + secret + "&code=" + code
				+ "&grant_type=authorization_code";

		String resultStr = HttpUtils.get(url);
//		logger.info("return data " + resultStr);
		WeChatUtil.isSuccess(resultStr);
		return JSONObject.parseObject(resultStr, OAuthAccessToken.class);
	}

	/**
	 * 根据code获取OAuthAccessToken
	 * 
	 * 对应文档认证步骤3
	 * @param token
	 * @return
	 */
	private OAuthAccessToken callForOAuthAccessTokenByRefreshToken(String refreshToken) {
		String appid = Config.instance().getAppid();
		String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="
				+ appid
				+ "&grant_type=refresh_token&refresh_token="
				+ refreshToken;

		String resultStr = HttpUtils.get(url);
//		logger.info("return data " + resultStr);
		try {
			WeChatUtil.isSuccess(resultStr);
		} catch (WeChatException e) {
//			logger.error(e.getMessage());
			e.printStackTrace();
			return null;
		}
		return JSONObject.parseObject(resultStr, OAuthAccessToken.class);
	}

	/**
	 * 根据token获取OAuthUserInfo 
	 * 
	 * 对应文档认证步骤4
	 * @param token
	 * @return
	 */
	private OAuthUserInfo callForOAuthUserinfo(OAuthAccessToken token) {
		String url = "https://api.weixin.qq.com/sns/userinfo?access_token="
				+ token.getAccess_token() + "&openid=" + token.getOpenid()
				+ "&lang=zh_CN";
		String resultStr = HttpUtils.get(url);
//		logger.info("return data " + resultStr);
		try {
			WeChatUtil.isSuccess(resultStr);
		} catch (WeChatException e) {
//			logger.error(e.getMessage());
			e.printStackTrace();
			return null;
		}
		return JSONObject.parseObject(resultStr, OAuthUserInfo.class);
	}

	public OAuthAccessToken getOAuthAccessToken() {
		return oAuthAccessToken;
	}

	public OAuthUserInfo getOAuthUserInfo() {
		return oAuthUserInfo;
	}

}
